﻿// fix_arpa_by_words.cpp: 定义控制台应用程序的入口点。
//

#include "fix_arpa_by_words.h"

#define  BOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE

bool CheckFileOrDirectory(const char* directory) {
	using namespace boost::filesystem;
	namespace bf = boost::filesystem;
	bf::path this_path(directory);
	if ( ! bf::exists(this_path))
	{
		std::cout << directory << "is not exists.\n";
		return false;
	}
	return true;

}


int ReadWords(const char* words_name,
	std::unordered_map<string, string>& words) {
	if (! words_name)
	{
		return 0;
	}
	int num_words = 0;
	ifstream fp_words(words_name, ios::in);
	if (fp_words.is_open())
	{
		std::string next_token, according_id;
		while ( ! fp_words.eof())
		{
			fp_words >> next_token;
			fp_words >> std::ws;
			fp_words >> according_id;
			fp_words >> std::ws;
			if (! next_token.empty() && ! according_id.empty())
			{
				words[next_token] = according_id;
				next_token.clear();
				according_id.clear();
				num_words++;
			}
		}
	}
	fp_words.close();
	return num_words;
}


bool IsArpaEntryInWords(const std::string& token,
	const std::unordered_map<string, string>& words) {
	if (! token.empty()){
		return false;
	}
	std::unordered_map<string, string>::const_iterator it =
		words.find(token), end = words.end();
	if (it == end){
		return false;
	}
	return true;
}

int ProcessArpa(const char* arap_name,
	const unordered_map<string, string>& words) {
	if (words.size() == 0)
	{
		return -1;
	}
	unsigned long long num_remain_entries = 0;
	std::string processed_arpa = arap_name;
	processed_arpa.append(".processed");
	std::ofstream fp_proc(processed_arpa.c_str(), ios::out);
	if (! fp_proc.is_open())
	{
		return -1;
	}
	std::ifstream fp_arpa(arap_name, ios::in);
	if (fp_arpa.is_open())
	{
		std::string arpa_entry, entry_units;
		std::vector<std::string> units;
		while (std::getline(fp_arpa, arpa_entry, '\n'))
		{
			if (! arpa_entry.empty())
			{
				units = SplitString(arpa_entry);
				bool is_oov_found = false;
				for (int i=0;i<units.size();i++)
				{
					if(IsSpecialArpaToken(units[i].c_str()) ) continue;
					is_oov_found = IsArpaEntryInWords(units[i], words);
				}
				if(! is_oov_found)
				{
					fp_proc << arpa_entry;
					fp_proc << "\n";
				}

				num_remain_entries++;
			}
			else
				fp_proc << "\n";
		}
	}
	fp_arpa.close();
	fp_proc.close();
	return num_remain_entries;
}


std::vector<string> SplitString(const std::string& entry) {
	std::vector<string> units;
	if ( entry.empty()){
		return units;
	}
	string long_string = entry, sub_token;
	
	std::stringstream ss(long_string);
	while ( ! ss.eof())
	{
		ss >> sub_token;
		if (! sub_token.empty()){
			units.push_back(sub_token);
		}
		ss >> std::ws;
	}
	return units;
}


bool IsSpecialArpaToken(const char* sub_token) {
	if (! sub_token){
		return false;
	}
	string token = sub_token;
	if (token[0] == '-' || token[0] == '\\'){
		return true;
	}
	return false;
}



int FixArpaByWords(const char* arpa, const char* words)
{
	std::string arpa_name = arpa, words_name = words;
	if (!CheckFileOrDirectory(arpa_name.c_str()) ||
		!CheckFileOrDirectory(words_name.c_str()))
	{
		return false;
	}
	std::unordered_map<string, string> words_dict;
	if (ReadWords(words_name.c_str(), words_dict) > 0 &&
		ProcessArpa(arpa_name.c_str(), words_dict) > 0)
	{
		return 0;
	}
	else
	{
		std::cout << "Reading or Processing Arpa file failed.\n";
		return -1;
	}
}

